#pragma once

#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QDebug>
#include <QFileInfo>

#include "base.qpb.h"
#include "gateway.qpb.h"
#include "user.qpb.h"
#include "notify.qpb.h"
#include "speech.qpb.h"
#include "message.qpb.h"
#include "friend.qpb.h"
#include "file.qpb.h"
#include "transmite.qpb.h"


namespace model
{
/*
    工具函数
*/

static inline QString getFileName(const QString& path){
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__), QString::number(__LINE__))
//noquote 可以让日志打印的时候不再带上""
#define LOG() qDebug().noquote() << TAG

static inline QString formatTime(int64_t timestamp){
    //将时间戳转换为QDateTime
    QDateTime datetime = QDateTime::fromSecsSinceEpoch(timestamp);

    return datetime.toString("yyyy-MM-dd HH:mm:ss");
}

static inline int64_t getTime(){
    return QDateTime::currentSecsSinceEpoch();
}

static inline QString createId(){
    return "M" + QUuid::createUuid().toString().sliced(25,12);
}

//根据QByteArray 转换为 QIcon
static inline QIcon createIcon(const QByteArray& byteArray){
    QPixmap pixmap;
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

//  读写文件操作
//  从指定的文件中读取所有的二进制内容，得到QByteArray
static inline QByteArray loadFileToQByteArray(const QString& path){
    QFile file(path);

    bool ok = file.open(QFile::ReadOnly);
    if(!ok){
        qDebug() << "文件打开失败";
        return QByteArray();
    }

    QByteArray content = file.readAll();
    file.close();
    return content;
}

//  将QByteArray写到指定的文件中
static inline void writeByteArrayToFile(const QString& path,const QByteArray& content){
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);
    if(!ok){
        qDebug() << "文件打开失败";
        return;
    }

    file.write(content);
    file.flush();
    file.close();
}

/*
    用户信息
*/

class UserInfo {
public:
    QString userId = "";         // 用户编号
    QString nickname = "";       // 用户昵称
    QString description = "";    // 用户签名
    QString phone = "";          // 手机号码
    QIcon avatar;                // 用户头像

    void load(const lch_im::UserInfo& userInfo) {
        this->userId = userInfo.userId();
        this->nickname = userInfo.nickname();
        this->description = userInfo.description();
        this->phone = userInfo.phone();
        if(userInfo.avatar().isEmpty()) {
            //使用默认头像
            this->avatar = QIcon(":/resource/image/avatarDefault.png");
        }else {
            this->avatar = createIcon(userInfo.avatar());
        }

    }
};

/*
    消息信息
*/

enum MessageType{
    TEXT_TYPE,                  // 文本消息
    FILE_TYPE,                  // 文件消息
    IMAGE_TYPE,                 // 图片消息
    SPEECH_TYPE                 // 语音消息
};

class Message {
public:
    QString messageId = "";             // 消息ID
    QString chatSessionId = "";         // 消息属于会话的ID
    QString time = "";                  // 消息的时间 通过格式化的方式 比如 2024-09-09
    MessageType messageType;            // 消息类型
    UserInfo sender;                    // 发送者的消息
    QByteArray content;                 // 消息内容
    QString fileId = "";                // 文件的身份标识，当消息是文件 图片  语音 才有效 如果是文本就为""
    QString fileName = "";              // 文件名称，只是当消息类型为 文件消息的时候才有效，其他消息为""

    // 此处 extraInfo 目前只是在消息类型为文件消息时, 作为 "文件名" 补充.
    static Message createMessage(MessageType messageType, const QString& chatSessionId, const UserInfo& sender,
                               const QByteArray& content, const QString& extraInfo) {
        if (messageType == TEXT_TYPE) {
            return createTextMessage(chatSessionId, sender, content);
        } else if (messageType == IMAGE_TYPE) {
            return createImageMessage(chatSessionId, sender, content);
        } else if (messageType == FILE_TYPE) {
            return createFileMessage(chatSessionId, sender, content, extraInfo);
        } else if (messageType == SPEECH_TYPE) {
            return createSpeechMessage(chatSessionId, sender, content);
        } else {
            // 触发了未知的消息类型
            return Message();
        }
    }

    static Message messageFactory(MessageType messageType,const QString& chatSessionId,const UserInfo& sender,
                                  const QByteArray& content,const QString& extraInfo){
        if(messageType == TEXT_TYPE){
            return createTextMessage(chatSessionId,sender,content);
        }else if(messageType == FILE_TYPE){
            return createFileMessage(chatSessionId,sender,content,extraInfo);
        }else if(messageType == IMAGE_TYPE){
            return createImageMessage(chatSessionId,sender,content);
        }else if(messageType == SPEECH_TYPE){
            return createSpeechMessage(chatSessionId,sender,content);
        }else {
            return Message();
        }
    }

    void load(const lch_im::MessageInfo& messageInfo) {
        this->messageId = messageInfo.messageId();
        this->chatSessionId = messageInfo.chatSessionId();
        //int64转换为string类型
        this->time = formatTime(messageInfo.timestamp());
        this->sender.load(messageInfo.sender());

        // 设置消息类型
        auto type = messageInfo.message().messageType();
        if (type == lch_im::MessageTypeGadget::MessageType::STRING) {
            this->messageType = TEXT_TYPE;
            this->content = messageInfo.message().stringMessage().content().toUtf8();
        } else if (type == lch_im::MessageTypeGadget::MessageType::IMAGE) {
            this->messageType = IMAGE_TYPE;
            if (messageInfo.message().imageMessage().hasImageContent()) {
                this->content = messageInfo.message().imageMessage().imageContent();
            }
            if (messageInfo.message().imageMessage().hasFileId()) {
                this->fileId = messageInfo.message().imageMessage().fileId();
            }
        } else if (type == lch_im::MessageTypeGadget::MessageType::FILE) {
            this->messageType = FILE_TYPE;
            if (messageInfo.message().fileMessage().hasFileContents()) {
                this->content = messageInfo.message().fileMessage().fileContents();
            }
            if (messageInfo.message().fileMessage().hasFileId()) {
                this->fileId = messageInfo.message().fileMessage().fileId();
            }
            this->fileName = messageInfo.message().fileMessage().fileName();
        } else if (type == lch_im::MessageTypeGadget::MessageType::SPEECH) {
            this->messageType = SPEECH_TYPE;
            if (messageInfo.message().speechMessage().hasFileContents()) {
                this->content = messageInfo.message().speechMessage().fileContents();
            }
            if (messageInfo.message().speechMessage().hasFileId()) {
                this->fileId = messageInfo.message().speechMessage().fileId();
            }
        } else {
            // 错误的类型
            LOG() << "非法的消息类型! type=" << type;
        }
    }


private:
    static Message createTextMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = createId();
        message.chatSessionId = chatSessionId;
        message.time = formatTime(getTime());
        message.messageType = TEXT_TYPE;
        message.sender = sender;
        message.content = content;
        message.fileId = "";
        message.fileName = "";

        return message;
    }

    static Message createFileMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content,const QString& fileName){
        Message message;
        message.messageId = createId();
        message.chatSessionId = chatSessionId;
        message.time = formatTime(getTime());
        message.messageType = FILE_TYPE;
        message.sender = sender;
        message.content = content;
        message.fileId = "";
        message.fileName = fileName;

        return message;
    }

    static Message createImageMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = createId();
        message.chatSessionId = chatSessionId;
        message.time = formatTime(getTime());
        message.messageType = IMAGE_TYPE;
        message.sender = sender;
        message.content = content;
        message.fileId = "";

        return message;
    }

    static Message createSpeechMessage(const QString& chatSessionId,const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = createId();
        message.chatSessionId = chatSessionId;
        message.time = formatTime(getTime());
        message.messageType = SPEECH_TYPE;
        message.sender = sender;
        message.content = content;
        message.fileId = "";

        return message;
    }
};

/*
    会话信息
*/

class ChatSessionInfo {
public:
    QString chatSessionId = "";             //  会话编号
    QString chatSessionname = "";           //  会话名字，如果是单聊，就是对方的名字，如果是群聊，那么就是群聊的名称
    Message lastMessage;                    //  最新的消息
    QIcon avatar;                           //  会话的头像
    //如果是单聊，那么userId就是对方的用户Id
    //如果是群聊，那么userId就设置为"",通过其他方式把完整的用户ID列表拿到
    QString userId = "";

    void load(const lch_im::ChatSessionInfo& chatSessionInfo) {
        this->chatSessionId = chatSessionInfo.chatSessionId();
        this->chatSessionname = chatSessionInfo.chatSessionName();
        if (chatSessionInfo.hasSingleChatFriendId()) {
            this->userId = chatSessionInfo.singleChatFriendId();
        }
        if(chatSessionInfo.hasPrevMessage()) {
             lastMessage.load(chatSessionInfo.prevMessage());
        }

        if(chatSessionInfo.hasAvatar() && chatSessionInfo.avatar().isEmpty()) {
            //已经有头像了
            this->avatar = createIcon(chatSessionInfo.avatar());
        }else {
            //没有头像，如果是单聊就设置为对方的头像，如果是群聊，就设置为默认的群聊头像
            if(userId != "") {
                //单聊
                this->avatar = QIcon(":/resource/image/avatarDefault.png");
            }else {
                this->avatar = QIcon(":/resource/image/groupAvatar.png");
            }
        }
    }
};

} // end of model
